﻿/*
 * copyright (c) 2009 hvbird
 *
 * This file is part of tdlib.
 *
 * tdlib is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * tdlib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

namespace TDLib.Rss
{
    public class RSSChannel
    {
        ////////////////////////////
        // RSSChannel implementation

        /// <summary>Channel name.</summary>
        string m_strName = "";

        /// <summary>Channel title.</summary>
        string m_strTitle = "";

        /// <summary>Channel url.</summary>
        string m_strUrl = "";

        /// <summary>Publication timestamp.</summary>
        string m_strPublished = "";

        /// <summary>Collection of RSSItems.</summary>
        List<RSSItem> m_items = new List<RSSItem>();

        /// <summary>
        /// Constructs an RSSChannel.
        /// </summary>
        /// <param name="strName">Channel name.</param>
        /// <param name="strUrl">Channel URL.</param>
        public RSSChannel
          (string strName,
           string strUrl)
        {
            m_strName = strName;
            m_strUrl = strUrl.Trim();
        }

        /////////////
        // Properties

        /// <summary>
        /// The channel's name.
        /// </summary>
        public string Name
        {
            get
            {
                return m_strName;
            }
        }

        /// <summary>
        /// The channel's title.
        /// </summary>
        public string Title
        {
            get
            {
                return m_strTitle;
            }
        }

        /// <summary>
        /// The channel's last updated timestamp.
        /// </summary>
        public DateTime Updated
        {
            get
            {
                DateTime tmUpdated = DateTime.MinValue;
                try
                {
                    tmUpdated = DateTime.Parse(m_strPublished);
                }
                catch (Exception)
                {
                    // Nothing to do
                }
                return tmUpdated;
            }
        }

        /// <summary>
        /// Collection of retrieved RSSItems.
        /// </summary>
        public List<RSSItem> Items
        {
            get
            {
                return m_items;
            }
        }

        /////////////
        // Operations

        /// <summary>
        /// Retrieves the channel's collection of RSSItems.
        /// </summary>
        public void FetchItems()
        {
            if ((m_strUrl != null) && (m_strUrl.Length > 0))
            {
                parseContent();
            }
        }

        /////////////////////////////////////
        // WebResourceProvider implementation

        /// <summary>
        /// Returns the url to be fetched.
        /// </summary>
        /// <returns>The url to be fetched.</returns>
        protected string getFetchUrl()
        {
            return m_strUrl;
        }

        /// <summary>
        /// Provides the derived class to parse the fetched content.
        /// </summary>
        protected void parseContent()
        {
            Web.NetHttp http = new TDLib.Web.NetHttp();
            http.Method = "GET";
            http.MyEncoding = "utf-8";

            string htmlstr = http.GetUrl(m_strUrl);

            //检查编码是否一致，否则重新抓取
            string encode = SearchStr(htmlstr, @"encoding=""(?<search>.*?)""").ToUpper();
            if(encode.Length>0 && encode != http.MyEncoding)
            {
                http.MyEncoding = encode;
                htmlstr = http.GetUrl(m_strUrl);
            }
            
            // Get root "rss" element - return if none
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.InnerXml = htmlstr;
            XmlElement rootEle = xmlDoc.DocumentElement;
            if (!rootEle.Name.Equals("rss"))
                return;

            // Get "channel" element - return if none
            XmlNodeList elements = rootEle.GetElementsByTagName("channel");
            if (elements.Count == 0)
                return;
            XmlElement channelEle = elements.Item(0) as XmlElement;

            // Get channel title - return if missing
            elements = channelEle.GetElementsByTagName("title");
            if (elements.Count == 0)
                return;
            XmlElement ele = elements.Item(0) as XmlElement;
            m_strTitle = ele.InnerText;

            // Get optional publication timestamp - return if missing
            elements = channelEle.GetElementsByTagName("pubDate");
            if (elements.Count == 0)
                elements = channelEle.GetElementsByTagName("lastBuildDate");
            if (elements.Count != 0)
            {
                ele = elements.Item(0) as XmlElement;
                m_strPublished = ele.InnerText;
            }

            // Get items
            elements = channelEle.GetElementsByTagName("item");
            foreach (XmlElement element in elements)
            {
                RSSItem rssItem = RSSItem.createFromElement(element as XmlElement);
                if (rssItem != null)
                    m_items.Add(rssItem);
            }
        }

        ///////////////////
        // Object overrides

        /// <summary>
        /// Returns the name of the channel.
        /// </summary>
        /// <returns>Name of channel.</returns>
        public override string ToString()
        {
            return Name;
        }

        //正则查询
        private string SearchStr(string str, string reg)
        {
            Regex rx = new Regex(reg, RegexOptions.Compiled | RegexOptions.IgnoreCase);
            MatchCollection matches = rx.Matches(str);

            foreach (Match match in matches)
            {
                string word = match.Groups["search"].Value;
                return word;
            }

            return "";
        }
    }
}
